package com.designPattern.p01singleton;

/**
 * @program: 单例模式之懒汉模式（线程安全）--DCL双检查锁机制
 * @author: luhd
 * @create: 2021-08-24
 */
public class DLanhanSafe {
    // 将自身实例化对象声明为一个属性，用static修饰
    private static DLanhanSafe instance;        //   volatile 关键字  修饰     可以禁止jvm重排序
    // 私有的构造方法
    private DLanhanSafe(){}
    // 获取实例的getInstance方法
    public static DLanhanSafe getInstance(){
        //第一步检查instance有没有被实例化出来，如果没有进入if块----------->如果已经实例化了，可以直接返回    提高效率
        if(instance==null){
            synchronized (DLanhanSafe.class){
                if(instance==null){
                    // 内层的if判断 是单例模式的核心  保证instance只被实例化一次
                    // 某个线程取得了类锁，实例化对象前第二次检查instance是否已经被实例化出来，如果没有，才最终实例出对象
                    instance = new DLanhanSafe();
                }
            }
        }
        return instance;
    }

    // 当两个线程A和B同时进入方法时，加入A抢夺到锁，则A继续执行，当A执行到new操作时，由于new操作不是原子操作，且synchronized也不能禁止重排序，
    // 我们首先将new操作原子化：a-开辟内存空间；b-初始化对象；c-将引用赋值给变量
    // 正常的执行顺序应该是a-b-c，不禁止重排序的情况下可能是：a-c-b
    // 当线程A执行a-c，即将执行b的时候，由于cpu时间片结束，则有可能会让步给线程B，
    // 线程B进行第一次判断，singleton由于已经有了内存指向，并不为空，此时，对象还没有执行初始化，但已经判断为true，并且返回了。
    // 此时，就产生了严重的错误，因此需要 volatile 来禁止重排序。
}
